﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Navigation;
using Halfwit.Views;
using System.Windows.Threading;

namespace Halfwit.ViewModels
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            OpenUri = new RelayCommand("Open URI", GoToContentUri, ContentHasUri);
            Connection = new RelayCommand("Connection", GoConnection, CanGoConnection);
            Options = new RelayCommand("Options", GoOptions, CanGoOptions);
            About = new RelayCommand("About Halfwit", GoAbout);
            Home = new RelayCommand("Home", GoHome);
            Mentions = new RelayCommand("Mentions", GoMentions);
            Messages = new RelayCommand("Messages", GoMessages);
            Search = new RelayCommand("Search", GoSearch);

            _homeVM = new HomeViewModel(this);
            _mentionsVM = new MentionsViewModel(this);
            _messagesVM = new MessagesViewModel(this);

            // seed Notify with a "do nothing" action
            Notify = _ => { };
        }

        private HomeViewModel _homeVM;
        private MentionsViewModel _mentionsVM;
        private MessagesViewModel _messagesVM;

        private void GoToContentUri(object o)
        {
            var text = o as String;
            if (text == null)
            {
                var t = NavigationService.Content as TweetsPage;
                if (t == null) return;
                text = ((TweetsViewModel)t.DataContext).Uri;
            }
            if (text == null) return;

            try
            {
                System.Diagnostics.Process.Start(text);
            }
            catch (Win32Exception)
            {
            }
        }

        private bool ContentHasUri(object o)
        {
            return (o != null) || (NavigationService != null && NavigationService.Content is TweetsPage);
        }

        private bool CanGoOptions(object o)
        {
            return NavigationService.Content is TweetsPage;
        }

        private void GoOptions(object o)
        {
            NavigationService.Navigate(new OptionsPage(new OptionsViewModel(this)));
        }

        private bool CanGoConnection(object o)
        {
            return NavigationService.Content is TweetsPage;
        }

        private void GoConnection(object o)
        {
            Action next;
            if (!NavigationService.CanGoBack)
            {
                next = () => Home.Execute(null);
            }
            else
            {
                next = () => NavigationService.GoBack();
            }
            NavigationService.Navigate(new LoginPage(new LoginViewModel(next)));
        }

        private void GoAbout(object o)
        {
            NavigationService.Navigate(new AboutPage());
        }

        private bool RefreshIfAlreadyViewing<T>() where T : TweetsViewModel
        {
            var tp = NavigationService.Content as TweetsPage;
            if (tp == null) return false;

            var model = tp.DataContext as T;
            if (model == null) return false;

            model.Refresh.Execute(null);
            return true;
        }

        private void GoHome(object o)
        {
            if (RefreshIfAlreadyViewing<HomeViewModel>()) return;

            NavigationService.Navigate(new TweetsPage(_homeVM));
        }

        private void GoMentions(object o)
        {
            if (RefreshIfAlreadyViewing<MentionsViewModel>()) return;

            NavigationService.Navigate(new TweetsPage(_mentionsVM));
        }

        private void GoSearch(object o)
        {
            var text = (o as String) ?? String.Empty;

            var vm = new SearchViewModel(this, text);
            if (Properties.Settings.Default.OpenLinksInBrowser)
            {
                System.Diagnostics.Process.Start(vm.Uri);
                return;
            }

            NavigationService.Navigate(new TweetsPage(vm));
        }

        private void GoMessages(object o)
        {
            if (RefreshIfAlreadyViewing<MessagesViewModel>()) return;

            NavigationService.Navigate(new TweetsPage(_messagesVM));
        }

        public NavigationService NavigationService { get; set; }
        public Action<String> Notify { get; set; }

        public ICommand OpenUri { get; private set; }
        public ICommand Connection { get; private set; }
        public ICommand Options { get; private set; }
        public ICommand About { get; private set; }
        public ICommand Home { get; private set; }
        public ICommand Mentions { get; private set; }
        public ICommand Messages { get; private set; }
        public ICommand Search { get; private set; }

        public void DeferRefresh(Action action)
        {
            var deferable = NavigationService.Content as IDeferable;
            if (deferable == null) return;

            using (deferable.DeferRefresh())
            {
                action();
            }
        }

        public void Connect()
        {
            Action goHome = () =>
            {
                Home.Execute(null);
            };

            if (TwitterConnection.Authenticate())
            {
                goHome();
                return;
            }

            // get them to authenticate
            Connection.Execute(null);
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
